import { logger } from './logger';
import * as vscode from 'vscode';
import { spawn } from 'child_process';

export function syncCode(args: any[]) {
    if (args.length === 0) {
        vscode.window.showErrorMessage('No args provided, please see the log for more information');
        logger.errorWithStack('No args provided');
        return;
    }

    const uri = args[0] as vscode.Uri;
    if (!uri || typeof uri.fsPath !== 'string') {
        vscode.window.showErrorMessage('Invalid URI provided, , please see the log for more information');
        logger.errorWithStack('Invalid URI provided');
        return;
    }

    let path = uri.fsPath;
    
    // Check if path is a file, if not, append bundle.json to it
    const fs = require('fs');
    if (fs.existsSync(path) && fs.statSync(path).isDirectory()) {
        path = `${path}/bundle.json`;
    }
    
    logger.info(`bundle.json's path is : ${path}`);
    const pathParts = path.split(/[/\\]/);
    const parentFolderName = pathParts.length >= 2 ? pathParts.slice(-2, -1)[0] : '';

    if (!parentFolderName) {
        vscode.window.showErrorMessage('Could not extract parent folder name from path, please see the log for more information');
        logger.errorWithStack('Could not extract parent folder name from path');
        return;
    }
    logger.info(`parentFolderName is : ${parentFolderName}`);


    const cancellationTokenSource = new vscode.CancellationTokenSource();
    
    vscode.window.withProgress({
        location: vscode.ProgressLocation.Notification,
        title: `[${parentFolderName}]: Begin to Sync Code...`,
        cancellable: true
    },
    async (progress, token) => {
        // Execute ls command
        const dirPath = path.substring(0, path.lastIndexOf('/'));
        
        try {
            // 执行命令
            const result = await executeAndLogCommand(dirPath, parentFolderName, token);

            if (result && result.status === 'success') {
                // 成功时的操作
                vscode.window.showInformationMessage(`[${parentFolderName}]: Sync Code Success`);
                return true;
            } else {
                vscode.window.showErrorMessage(`[${parentFolderName}]: Sync Code failed, ${result?.message}`);
                return false;
            }
        } catch (error) {
            // 发生错误时显示错误消息
            if (error instanceof Error) {
                logger.errorWithStack(error.message);
            } else {
                logger.errorWithStack("Sync Code failed");
            }
            vscode.window.showErrorMessage(`[${parentFolderName}]: Sync Code failed, Please check the log for more information`);     
            return false; // 表示操作失败
        }
    });

    
    


}


async function executeAndLogCommand(dirPath: string, parentFolderName: string, token?: vscode.CancellationToken) {
    try {
        logger.show();
        logger.info(`Begin to repo sync, dirPath is ${dirPath}, parentFolderName is ${parentFolderName}`);
        
        // 获取命令执行的工作目录（文件所在目录）
        let repoRootPath = dirPath;
        let foundRepoDir = false;
        
        while (repoRootPath && repoRootPath !== '/') {
            const potentialRepoDir = `${repoRootPath}/.repo`;
            const fs = require('fs');
            
            if (fs.existsSync(potentialRepoDir) && fs.statSync(potentialRepoDir).isDirectory()) {
                foundRepoDir = true;
                logger.info(`Found .repo directory at: ${repoRootPath}`);
                break;
            }
            
            // Move up one directory
            repoRootPath = repoRootPath.substring(0, repoRootPath.lastIndexOf('/'));
        }
        
        if (!foundRepoDir) {
            logger.error('Could not find .repo directory in any parent folder');
            vscode.window.showErrorMessage(`[${parentFolderName}]: Could not find .repo directory`);
            return { status: 'failed', message: 'Could not find .repo directory in any parent folder' };
        }

        // First run repo list to get the component name
        let componentName = parentFolderName;
        try {
            const { spawn } = require('child_process');
            const repoListProcess = spawn('repo', ['list'], { cwd: repoRootPath });
            
            let repoListOutput = '';
            
            repoListProcess.stdout.on('data', (data: Buffer) => {
                repoListOutput += data.toString();
            });
            
            await new Promise<void>((resolve, reject) => {
                repoListProcess.on('close', (code: number) => {
                    if (code === 0) {
                        resolve();
                    } else {
                        reject(new Error(`repo list command failed with code ${code}`));
                    }
                });
                
                repoListProcess.on('error', (err: Error) => {
                    reject(err);
                });
            });
            
            // Process the repo list output to find the component name
            const lines = repoListOutput.split('\n');
            const relativePath = dirPath.replace(repoRootPath + '/', '');
            
            logger.info(`Looking for component at relative path: ${relativePath}`);
            
            for (const line of lines) {
                // Fix for the correct format: "directory : component_name"
                const parts = line.trim().split(/\s*:\s*/);
                if (parts.length === 2) {
                    const path = parts[0].trim();
                    const name = parts[1].trim();
                    if (path && relativePath.startsWith(path)) {
                        componentName = name;
                        logger.info(`Found component name: ${componentName} for path: ${path}`);
                        break;
                    }
                }
            }
        } catch (error) {
            logger.warn(`Failed to get component name from repo list: ${error instanceof Error ? error.message : 'unknown error'}`);
            logger.info(`Falling back to parent folder name: ${parentFolderName}`);
        }
        
        let commandStr = `repo sync -c build ${componentName}`;
        if (componentName === 'build') {
            commandStr = `repo sync -c build`;
        }

        // commandStr = '../test.sh';
        
        // 将命令字符串分解为命令和参数
        const parts = commandStr.split(' ');
        const command = parts[0];
        const args = parts.slice(1);
        
        logger.info(`Executing command: ${commandStr} in directory: ${repoRootPath}`);
        
        const process = spawn(command, args, { 
            cwd: repoRootPath
        });

        // 实时处理标准输出
        process.stdout.on('data', (data) => {
            const output = data.toString().trim();
            if (output) {
                output.split('\n').forEach((line: string) => {
                    if (line.trim()) {
                        logger.repo(`  ${line}`);
                    }
                });
            }
        });
        
        // 实时处理标准错误
        process.stderr.on('data', (data) => {
            const output = data.toString().trim();
            if (output) {
                output.split('\n').forEach((line: string) => {
                    if (line.trim()) {
                        logger.repo(`  ${line}`);
                    }
                });
            }
        });
        
        return new Promise<{ status: string; message?: string }>((resolve, reject) => {
            // 保存对取消状态的引用
            let isCancelled = false;
            
            if (token) {
                token.onCancellationRequested(() => {
                    isCancelled = true;
                    process.kill();
                    logger.info(`Sync Code cancelled by user`);
                    resolve({ status: 'failed', message: 'Sync Code cancelled by user' });
                });
            }
            
            process.on('close', (code) => {
                // 如果已经因为取消而解析了，就不要重复解析
                if (isCancelled) {
                    return;
                }
                
                if (code === 0) {
                    resolve({ status: 'success' });
                } else {
                    const errorMsg = `命令 ${commandStr} 执行失败，退出码: ${code}`;
                    logger.errorWithStack(errorMsg);
                    reject({ status: 'failed', message: "please check the log for more information" });
                }
            });
            
            process.on('error', (err) => {
                // 如果已经因为取消而解析了，就不要重复解析
                if (isCancelled) {
                    return;
                }
                
                logger.errorWithStack(`command execution error: ${err.message}`);
                reject({ status: 'failed', message: "please check the log for more information" });
            });
        });
    } catch (error) {
        if (error instanceof Error) {
            logger.errorWithStack(`执行命令时出错: ${error.message}`);
        } else {
            logger.errorWithStack(`执行命令时发生未知错误`);
        }
        return { status: 'failed', message: 'please check the log for more information' };
    }
}